package server

import (
	"context"
	"encoding/json"
	"github.com/spf13/pflag"
	"github.com/spf13/viper"
	"gluenet/modules/strategies/iot-car/algorithm"
	"gluenet/modules/strategies/iot-car/data"
	"gluenet/modules/strategies/iot-car/worker"
	"gluenet/pkg/apis"
	v12 "gluenet/pkg/log/v1"
	"gluenet/pkg/nets"
	v1 "gluenet/utils/rpc/labels"
	"net/http"
	"strings"
)

type Server struct {
	ctx context.Context

	logger v12.Logger

	nets nets.GlueNets

	worker           *worker.Worker
	guid             string
	interferenceGuid string
}

func (r *Server) InitFlag(flags *pflag.FlagSet) {
	flags.String("guid", "123", "")
	flags.String("inter-guid", "17772419e93b497fbb85582cd41ec460_cpu-interference", "")
	r.nets.InitFlag(flags)
}

func (r *Server) ViperConfig(viper *viper.Viper) {

}

func (r *Server) InitViper(viper *viper.Viper) {
	//r.ip = viper.GetString("server.ip")
	r.nets.InitViper(viper)
	r.guid = viper.GetString("guid")
	r.interferenceGuid = viper.GetString("inter-guid")

	mode := viper.GetString("mode")
	if mode != "test" {
		r.guid = viper.GetString("GUID")
	}
}

func (r *Server) Initialize() {
	r.logger = v12.NewLogger("runner")

	if err := r.nets.Connect(); err != nil {
		r.logger.Fatalf("net connet %v", err)
	}

	algorithm.Install()

	guid := strings.Split(r.guid, "_")[0]

	r.logger.Debugf("listen topic %v", strings.Join([]string{r.guid, v1.StrategyControlApplicationSet}, ":"))
	r.nets.Subscribe(strings.Join([]string{guid, v1.StrategyControlApplicationSet}, ":"), func(m nets.NetContext) {
		if r.worker != nil {
			r.worker.Close()
			r.worker = nil
		}

		r.logger.Infof("reciv guids %s", m.Data.Data)

		apps, err := getData(m.Data.Data)
		if err != nil {
			responseFail(&m, err)
			r.logger.Errorf("get guids %v", err)
			return
		}

		r.logger.Infof("reciv guids %v", apps)

		wk := worker.NewWorker(r.ctx)
		go wk.Run(r.nets, r.logger, apps)
		r.worker = wk

		reply, _ := json.Marshal(map[string]interface{}{
			"code":    200,
			"message": "succeed",
			"data":    nil,
		})
		m.Data.IRespond(reply)
	})

	r.logger.Infof("server initialize finished, guid %v", r.guid)

	<-r.ctx.Done()
}

func (r *Server) Close() {

}

func NewServer(ctx context.Context) *Server {

	return &Server{
		ctx:    ctx,
		logger: v12.NewLogger("server"),
		nets:   nets.NewNets(ctx, "server.rpc"),
	}
}

func getData(bts []byte) (*data.Data, error) {
	var data = data.Data{}
	if err := json.Unmarshal(bts, &data); err != nil {
		return nil, err
	}
	return &data, nil
}

func responseFail(ctx *nets.NetContext, err error) {
	var resp = &apis.IResponse{
		Code:    http.StatusBadRequest,
		Message: err.Error(),
		Data:    nil,
	}
	bts, _ := json.Marshal(resp)
	ctx.Data.IRespond(bts)
}
